查看原文
其他

通过BLECTF入门BLE

Arahat0 看雪学苑 2024-07-16

iot小白最近入门BLE,看到yichen115师傅关于BLECTF的文章,感觉挺不错的,同时去年该项目有了更新,就自己试着做了做。并且针对yichen115师傅文章没写的地方进行补充。





环境搭建


首先你得有一块esp32的板子跟一个支持linux平台的蓝牙适配器或者USB加密狗。

安装esptool工具,这是一个基于 Python、开源、独立于平台的实用程序,用于与 Espressif 芯片中的 ROM 引导加载程序进行通信。我们得用它来烧录。

sudo apt-get install esptool

构建ble_ctf项目,/dev/ttyUSB0是我们的串口名称。

git clone https://github.com/hackgnar/ble_ctf
cd ble_ctf
esptool -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size 2MB --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/ble_ctf.bin





相关知识


hcitool


在打开蓝牙设备后,就可以使用hcitool工具来对BLE设备进行控制。

这个项目就需要使用hcitool搜索BLE设备来找到我们蓝牙设备的MAC地址。

sudo hcitool lescan


GATT


通用属性配置文件(GATT)详细描述了BLE设备建立连接后如何传输属性(数据),其中有三个相当重要的概念:Profile(配置文件)、Service(服务)、Characteristics(特征),它们可以抽象成以下包含关系:


首先GATT主要是负责在两个已经连接的设备交互数据,定义了BLE网络堆栈的一般拓扑的GAP层把BLE设备区分为主机Master(Central)和从机Slave(Perpherial)。一般我们将从机具有的数据或者属性特征,称之为Profile(配置文件)。

一个或多个Characteristic组成一个Service,一个或多个Service组成Profile。

主机可以发现和获取从机的ServiceCharacteristic,然后与之通信。Service可以理解为一个功能集合,Characteristic是主从通信的最小单元,是一个抽象功能单元。

◆主机可主动向从机Write写入或Read读取数据。

◆从机可主动向主机Notify通知数据。


而在GATT层则区分为ServerClient。

◆客户端(Client):客户端可以发送请求给GATT服务端,读取和写入存储在服务端的特征值(Characteristics )。

◆服务端(Server):该设备包含由GATT客户端读取或写入的Characteristic,每当客户端发送请求时,服务端就会接受并执行相应的请求。


Characteristic一般包含以下特征:

◆UUID(Universally Unique Identifier):用于唯一标识Characteristic。

◆Properties(属性):指定了Characteristic的行为,例如读取、写入、通知等。

◆Value(值):存储Characteristic的当前值。

◆Descriptors(描述符):提供了关于Characteristic的更多信息,如读写权限、单位、格式等。


比如我现在的服务端是我的烧录了BLECTFesp32,它由很多Characteristic组成。


拿着为0x45的handle举例,它就相当于某个Characteristic的编号
去读取这个0x45的handleValue/Descriptor,可以得到以下信息。


1a就是特征属性,代表权限。
46是这个特征的特征值的句柄 ,我们可以通过其去查看这个特征的描述。
00 0f ffUUID的缩略。

通过0x46的handle去读取Value/Descriptor,得到的就是这个特征的描述。


通过uuid去读取也是一样的结果。


在BLE中,我们有时候会看到Attributes(属性),这是一个更一般的术语,用于表示特征中的各种信息。它可以包含Characteristic的UUID、Properties、Value、Descriptors等。Attributes用于描述和定义特征的各个方面,以便设备之间能够理解和交换数据。

gatttool


hcitool对于BLE设备只能进行连接上的管理,如果需要更精细化的管理,就需要使用gatttool。

GATT commands
--primary 用于进行主服务发现,查找蓝牙设备上的主服务
--characteristics 用于进行特征发现,查找指定主服务下的特征
--char-read 用于写入特征的值,需要指定一个句柄
--char-write 用于写入特征的值,不需要响应
--char-write-req 用于写入特征的值,需要响应
--char-desc 于进行特征描述符发现,查找指定特征下的描述符
--listen 监听特征的通知和指示

Primary Services/Characteristics arguments
-s, --start=0x0001 用于指定起始句柄(可选)
-e, --end=0xffff 用于指定结束句柄(可选)
-u, --uuid=0x1801 用于指定16bit或者128bit的UUID(可选)

Characteristics Value/Descriptor Read/Write arguments
-a, --handle=0x0001 用于指定要读取或写入的特征或描述符的句柄
-n, --value=0x0001 用于指定要写入的特征值

Application Options:
-i, --adapter=hciX 用于指定本地适配器接口,如hci0
-b, --device=MAC 用于指定远程蓝牙设备的MAC地址
-t, --addr-type=[public | random] 用于设置LE地址类型,可以选择公共地址还是随机地址,默认公共地址
-m, --mtu=MTU 用于指定ATT协议MTU大小
-p, --psm=PSM 用于指定GATT/ATT over BR/EDR的PSM
-l, --sec-level=[low | medium | high] 用于设置安全级别,可以选择低、中、高,默认低安全级别
-I, --interactive 用于启用交互模式

交互模式下的命令。

help 显示帮助信息
exit 退出交互模式
quit 退出交互模式
connect [address [address type]] 连接到远程设备
disconnect 断开与远程设备的连接
primary [UUID] 发现主要服务
included [start hnd [end hnd]] 查找包含的服务
characteristics [start hnd [end hnd [UUID]]] 发现特征
char-desc [start hnd] [end hnd] 发现特征描述符
char-read-hnd <handle> 通过句柄读取特征值/描述符
char-read-uuid <UUID> [start hnd] [end hnd] 通过UUID读取特征值/描述符
char-write-req <handle> <new value> 写入特征值(写请求)
char-write-cmd <handle> <new value> 写入特征值(无响应)
sec-level [low | medium | high] 设置安全级别,默认为低安全级别
mtu <value> 设置交换GATT/ATT的MTU(最大传输单元)

我们这里可以查看一下设备上所有的特征(Characteristic)。

gatttool -b 08:B6:1F:B9:59:72 --characteristics

handle是特征的句柄,char properties是特征的属性,char value handle是特征值的句柄,uuid是特征的通用唯一标识符。




关卡


◆使用gatttool查看分数

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'

◆使用gatttool提交flag获得分数

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x002c -n $(echo -n "some flag value"|xxd -ps)


Flag1

Flag one is a gift! You can only obtain it by reading this document or peaking at the source code. In short, this flag is to get you familiar with doing a simple write to a BLE handle. Do the following to get your first flag. Make sure you replace the MAC address in the examples below with your devices mac address!

这关主要是让我们熟悉对BLE句柄的特征进行简单的写入。

首先,查看分数,初始分数为0/20。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'

然后,提交向0x2c句柄提交flag。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x002c -n $(echo -n "12345678901234567890"|xxd -ps)

最后,检查我们的分数来查看flag是否被接受,发现分数变成了1/20。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'


Flag 0x002e

Check out the ascii value of handle 0x002e and submit it to the flag submision handle 0x002c. If you are using gatttool, make sure you convert it to hex with xxd. If you are using bleah, you can send it as a string value.

读取0x002e句柄的特征,只需要--char-read-a指定0x002e。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x002e

转为ASCII值为d205303e099ceff44835。


Flag 0x0030

Check out the ascii value of handle 0x0030. Do what it tells you and submit the flag you find to 0x002c.

跟上一题差不多。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0030

转为ASCII值为MD5 of Device Name。

之前用hcitool扫描出的结果就是设备名加MAC地址。


将设备名BLECTF进行MD5加密后得到值取前20位就是flag。


Flag 0x0016

Bluetooth GATT services provide some extra device attributes. Try finding the value of the Generic Access -> Device Name.

首先我们得知道Generic Access服务的UUID是预定义为00001800-0000-1000-8000-00805f9b34fb。

使用--primary指令来发现所有的GATT主服务。

gatttool -b 08:B6:1F:B9:59:72 --primary

从输出可以看到第二个服务的uuid就是00001800-0000-1000-8000-00805f9b34fb,所以第二个服务就是Generic Access,根据它提供的句柄范围再去查看特征与句柄。

gatttool -b 08:B6:1F:B9:59:72 --characteristics --start=0x0014 --end=0x001c

一般第一个就是我们的设备。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0016

转为ASCII值为2b00042f7481c7b056c4b410d28f33cf取前20位。


Flag 0x0032

Read handle 0032 and do what it says. Notice that its not telling you to write to the flag handle as you have been. When you find the flag, go ahead and write it to the flag handle you have used in the past flags.

先读取看看0x0032句柄的特征的值。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0032

转ASCII值为Write anything here。

我们只需要往这个句柄里随便写点东西,这个特征的值就会变成flag。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0032 -n $(echo -n "2b00042f7481c7b056c4"|xxd -ps)
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0032

转为ASCII值为3873c0270763568cf7aa。


Flag 0x0034

Follow the instructions found from reading handle 0x0034. Keep in mind that some tools only write hex values while other provide methods for writing either hex or ascii
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0034

转为ASCII值为Write the ascii value "yo" here。


转为ASCII值为c55c6314b3db0a6128af。


Flag 0x0036

Follow the instructions found from reading handle 0x0036. Keep in mind that some tools only write hex values while other provide methods for writing either hex or ascii
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0036

转为ASCII值为Write the hex value 0x07 here。

我们之前写入的数据的格式都是字符串,现在需要的是整数类型,所以只需要-n直接接上对应的值就行了。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0036 -n 07

转为ASCII值为1179080b29f8da16ad66。


Flag 0x0038

Follow the instructions found from reading handle 0x0038. Pay attention to handles here. Keep in mind handles can be refrenced by integer or hex. Most tools such as gatttool and bleah allow you to specify handles both ways.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0038

转为ASCII值为Write 0xC9 to handle 58。

跟上一题差不多。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 58 -n C9
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 58
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x38

转为ASCII值为f8b136d937fad6a2be9f。


Flag 0x003c

Take a look at handle 0x003c and do what it says. You should script up a solution for this one. Also keep in mind that some tools write faster than others.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x003c

转为ASCII值为Brute force my value 00 to ff。

就是让我们写个脚本来往这个0x003c句柄的特征里写数据。

#!/bin/zsh

for value in $(seq 0 255); do
hex_value=$(printf "%02X" $value)
gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x003c -n $hex_value
sleep 0.5
done
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x3c

转为ASCII值为933c1fcfa8ed52d2ec05。


Flag 0x003e

Talke a look at handle 0x003e and do what it says. Keep in mind that some tools have better connection speeds than other for doing reads and writes. This has to do with the functionality the tool provides or how it uses cached BT connections on the host OS. Try testing different tools for this flag. Once you find the fastest one, whip up a script or bash 1 liner to complete the task. FYI, once running, this task takes roughly 90 seconds to complete if done right.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x003e

转为ASCII值为Read me 1000 times。

比上一个简单,时间间隔调小一点。

#!/bin/zsh

for ((i=1; i<=1000; i++)); do
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x3e
sleep 0.1
done
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x3e

转为ASCII值为6ffcd214ffebdc0d069e。


Flag 0x0040

Check out handle 0x0040 and google search gatt notify. Some tools like gatttool have the ability to subscribe to gatt notifications
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0040

转为ASCII值为Listen to me for a single notification,这个是让我们监听该句柄的一次通知。

因为主机可主动向从机Write写入或Read读取数据,从机可主动向主机Notify通知数据。

这里的命令分为两步,首先需要char-write-req -a 0x0040 -n 00,往该句柄以需要响应的形式写入数据,这样就可以启用通知。

然后--listen开启监听就能接收到该句柄发送的通知(Notify)和指示(indicate)。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0040 -n 00 --listen

转为ASCII值为5ec3772bcd00cf06d8eb。


Flag 0x0042

Check out handle 0x0042 and google search gatt indicate. For single response indicate messages, like this challenge, tools such as gatttool will work just fine.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0044

转为ASCII值为Listen to handle 0x0044 for a single indication,让我们监听该句柄的一次指示。

通知和指示在作用上很相似,都是在客户端发送请求后,服务器发相应的数据给客户端。不同的地方在协议层,通知是无应答的发送但是速度快,而指示是有应答机制的,更安全,它需要我们的客户端发送确认(ACK)来表示确认收到。

所以,其实gatttool的操作其实跟上一题一样。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0044 -n 00 --listen

转为ASCII值为c7b86dd121848c77c113。


Flag 0x0046

Check out handle 0x0046 and do what it says. Keep in mind that this notification clallange requires you to recieve multiple responses in order to complete.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0046

转为ASCII值为Listen to me for multi notifications,就是接收多个通知,没啥区别,因为我们的监听功能是持续的,能一直接收。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0046 -n 00 --listen

转为ASCII值为c9457de5fd8cafe349fdU no want this msg。


Flag 0x0048

Check out handle 0x0042 and google search gatt indicate. Keep in mind that this chalange will require you to parse multiple indicate responses in order to complete the chalange.

这里题目写错了,把0x0048写成了0x0042。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0048

转为ASCII值为Listen to handle 0x004a for multi indications,上题同理。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x004a -n 00 --listen

转为ASCII值为b6f3a47f207d38e16ffa。


Flag 0x004c

Check out handle 0x004c and do what it says. Much like ethernet or wifi devices, you can also change your bluetooth devices mac address.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x004c

转为ASCII值为Connect with BT MAC address 11:22:33:44:55:66
这个的意思其实就是让我们将我们蓝牙适配器的MAC地址改成11:22:33:44:55:66。

这里需要一个bdaddr工具(https://github.com/thxomas/bdaddr),根据这个项目的README,是支持我这个CSR4.0的蓝牙适配器的。但是如果你去看看这个项目issue,可以发现修改CSR的设备的MAC地址时会有问题,就是显示修改成功,但是实际MAC地址还是原来的那个,我自己在修改时也发现这个问题。不过后来,把蓝牙适配器拔了再插上去后去查看,发现MAC地址成功改变了!

sudo ./bdaddr -i hci0 11:22:33:44:55:66

转为ASCII值为aca16920583e42bdcf5f。


Flag 0x004e

Read handle 0x0048 and do what it says. Setting MTU can be a tricky thing. Some tools may provide mtu flags, but they dont seem to really trigger MTU negotiations on servers. Try using gatttool's interactive mode for this task. By default, the BLECTF server is set to force an MTU size of 20. The server will listen for MTU negotiations, and look at them, but we dont really change the MTU in the code. We just trigger the flag code if you trigger an MTU event with the value specified in handle 0x0048. GLHF!

这里题目写错了,把0x004e写成了0x0048。

gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x004e

转为ASCII值为Set your connection MTU to 444。

直接使用-m来设置有些问题,不过可以进入交互模式来设置。

gatttool -b 08:B6:1F:B9:59:72 -I
connect
mtu 444

转为ASCII值为b1e409e5a4eaf9fe5158。


Flag 0x0050

Check out handle 0x0050 and do what it says. This chalange differs from other write chalanges as your tool that does the write needs to have write response ack messages implemente correctly. This flag is also tricky as the flag will come back as notification response data even though there is no "NOTIFY" property.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0050

转为ASCII值为Write+resp 'hello',只需要注意只能使用--char-write-req,而不能使用--char-write就行了。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0050 -n $(echo -n "hello"|xxd -ps)

转为ASCII值为d41d8cd98f00b204e980。


Flag 0x0052

Take a look at handle 0x0052. Notice it does not have a notify property. Do a write here and listen for notifications anyways! Things are not always what they seem!
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0052

转为ASCII值为No notifications here! really?

这题的意思应该是,没有允许通知属性的句柄,也可能拥有通知的能力。

gatttool -b 08:B6:1F:B9:59:72 --characteristics

根据常见的特征属性及其对应的位标志:
◆0x01:允许广播
◆0x02:允许读取
◆0x04:允许写入(无响应)
◆0x08:允许写入(带响应)
◆0x10:允许通知(无确认)
◆0x20:允许通知(带确认)
◆0x40:允许经过身份签名的写入
◆0x80:运行扩展属性

我们0x0052句柄值对应属性值为0x0a,所以它应该只有写入和读取权限,但是我们主动向其写入输入来启用通知,从而监听服务端的通知。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0052 -n 00 --listen

转为ASCII值为fc920c68b6006169477b。


Flag 0x0054

Check out all of the handle properties on 0x0054! Poke around with all of them and find pieces to your flag.
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0054

转为ASCII值为So many properties!,我们可以看到该句柄属性值为0x9b,其对应权限为广播、读取、带响应写入、通知、扩展。


也就是说,我们可以写入,也可以监听。根据之前解题的思路,flag应该由此而来(什么MISC)。

gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0054 -n 00
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0054
gatttool -b 08:B6:1F:B9:59:72 --char-write-req -a 0x0054 -n 00 --listen

写入跟监听分别得到部分flag,转为ASCII值为fbb966958f07e4a0cc48。


Flag 0x0056

Figure out the authors twitter handle and do what 0x0056 tells you to do!
gatttool -b 08:B6:1F:B9:59:72 --char-read -a 0x0056

转为ASCII值为md5 of author's twitter handle。

作者的推特名在项目那里有:@hackgnar。

将其md5加密后取前20位得到d953bfb9846acc2e15ee。


至此,BLECTF挑战成功!

这个项目主要是引导我们使用gatttool工具去管理BLE设备,从而学习BLE的相关知识,总体体验下来还是挺不错的。

参考资料:
https://bbs.kanxue.com/thread-271543.htm
http://doc.iotxx.com/index.php?title=BLE技术揭秘#
https://leconiot.com/download/cc2640r2f/ble_stack_app/stack/gatt/gatt.html
https://www.cnblogs.com/iini/p/12334646.html




看雪ID:Arahat0

https://bbs.kanxue.com/user-home-964693.htm

*本文为看雪论坛精华文章,由 Arahat0 原创,转载请注明来自看雪社区



# 往期推荐

1、怎么让 IDA 的 F5 支持一种新指令集?

2、2024腾讯游戏安全大赛-安卓赛道决赛VM分析与还原

3、Windows主机入侵检测与防御内核技术深入解析

4、系统总结ARM基础

5、AliyunCTF 2024 - BadApple



球分享

球点赞

球在看



点击阅读原文查看更多

继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存